package com.onec.service.netty.websocket;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler.HandshakeComplete;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.undertow.websockets.WebSocketProtocolHandshakeHandler;
import io.undertow.websockets.core.WebSockets;

public class WebSocketService {


  static class EchoInitialization extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {

      ChannelPipeline channelPipeline = ch.pipeline();

      channelPipeline.addLast(new HttpRequestDecoder());
      channelPipeline.addLast(new HttpResponseEncoder());

      channelPipeline.addLast(new HttpObjectAggregator(65535));

      channelPipeline.addLast(new WebSocketServerProtocolHandler(
          "/ws", "ech", true, 10 * 1024));
      channelPipeline.addLast();

      channelPipeline.addLast();

    }
  }


  public static void start() {
    EventLoopGroup boss = new NioEventLoopGroup(1);
    EventLoopGroup work = new NioEventLoopGroup();
    ServerBootstrap bootstrap = new ServerBootstrap();
    bootstrap.group(boss, work)
        .channel(NioServerSocketChannel.class)
        .handler(new LoggingHandler(LogLevel.DEBUG))
        .childHandler(new EchoInitialization());

    try {
      Channel channel = bootstrap.bind(11122).sync().channel();
      channel.closeFuture().sync();
    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {
      boss.shutdownGracefully();
      work.shutdownGracefully();
    }
  }


  // 业务处理类
  class WebTextFrameHandler extends SimpleChannelInboundHandler<WebSocketFrame> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame msg) throws Exception {
      if (msg instanceof TextWebSocketFrame) {
        String request = ((TextWebSocketFrame) msg).text();

        TextWebSocketFrame textWebSocketFrame = new TextWebSocketFrame(request);
        ctx.channel().writeAndFlush(textWebSocketFrame);
      }
      throw new UnsupportedOperationException("异常");
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {

      if (evt instanceof HandshakeComplete) {
        ctx.pipeline().remove("");
      } else {
        super.userEventTriggered(ctx, evt);
      }
    }
  }
}
